#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
股票名称校对器模块
提供股票代码与名称的二次校对功能，确保识别准确性
"""

import os
import yaml
import logging
import re
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass

@dataclass
class StockInfo:
    """股票信息"""
    code: str
    name: str
    source: str  # config, manual, api等
    confidence: float = 1.0  # 置信度

class StockNameValidator:
    """股票名称校对器"""
    
    def __init__(self, config_path: str = 'config/stocks.yaml'):
        self.config_path = config_path
        self.logger = self._setup_logging()
        self.config_stock_names: Dict[str, str] = {}
        self.manual_stock_names: Dict[str, str] = {}
        self.validated_names: Dict[str, StockInfo] = {}
        
    def _setup_logging(self) -> logging.Logger:
        """设置日志"""
        logger = logging.getLogger('StockNameValidator')
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger
    
    def load_config_stock_names(self) -> Dict[str, str]:
        """从配置文件加载股票名称"""
        try:
            if not os.path.exists(self.config_path):
                self.logger.warning(f"配置文件不存在: {self.config_path}")
                return {}
            
            with open(self.config_path, 'r', encoding='utf-8') as f:
                config = yaml.safe_load(f)
            
            config_names = {}
            a_stocks = config.get('a_stocks', [])
            
            for stock_entry in a_stocks:
                if isinstance(stock_entry, str):
                    # 解析格式: '000001'  # 平安银行
                    stock_code = stock_entry.strip().strip("'\"")
                    config_names[stock_code] = f"股票{stock_code}"  # 默认名称
                    
            self.config_stock_names = config_names
            self.logger.info(f"从配置文件加载了 {len(config_names)} 个股票代码")
            return config_names
            
        except Exception as e:
            self.logger.error(f"加载配置文件失败: {e}")
            return {}
    
    def parse_config_with_comments(self) -> Dict[str, str]:
        """解析配置文件中的注释获取股票名称"""
        try:
            if not os.path.exists(self.config_path):
                return {}
            
            with open(self.config_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            stock_names = {}
            lines = content.split('\n')
            
            for line in lines:
                line = line.strip()
                if line.startswith('-') and '#' in line:
                    # 匹配格式: - '000001'  # 平安银行
                    parts = line.split('#', 1)
                    if len(parts) == 2:
                        stock_part = parts[0].strip()
                        name_part = parts[1].strip()
                        
                        # 提取股票代码
                        code_match = re.search(r"['\"]([0-9]{6})['\"]", stock_part)
                        if code_match:
                            stock_code = code_match.group(1)
                            stock_names[stock_code] = name_part
            
            self.config_stock_names = stock_names
            self.logger.info(f"从配置注释解析了 {len(stock_names)} 个股票名称")
            return stock_names
            
        except Exception as e:
            self.logger.error(f"解析配置文件注释失败: {e}")
            return {}
    
    def load_manual_stock_names(self) -> Dict[str, str]:
        """加载手动维护的股票名称映射"""
        manual_names = {
            # 基础股票
            "000001": "平安银行",
            "000001.SH": "上证指数",
            "000001.SZ": "平安银行",  # 错误格式，实际应该是000001
            "601611": "中国核建", 
            "002162": "悦心健康",
            "600019": "宝钢股份",
            "601668": "中国建筑",
            "603993": "洛阳钼业",
            "002625": "光启技术",
            "600435": "北方导航",
            "000426": "兴业银锡",
            "000975": "山金国际",
            "600967": "内蒙一机",
            "600961": "株冶集团",
            
            # ETF
            "512660": "军工ETF",
            "510050": "上证50ETF",
            "510300": "沪深300ETF", 
            "159922": "中证500ETF",
            
            # 其他常见股票
            "600519": "贵州茅台",
            "000858": "五粮液",
            "600036": "招商银行",
            "601318": "中国平安",
            "000002": "万科A",
            "002415": "海康威视",
            "300750": "宁德时代",
            "600276": "恒瑞医药",
        }
        
        self.manual_stock_names = manual_names
        self.logger.info(f"加载了 {len(manual_names)} 个手动维护的股票名称")
        return manual_names
    
    def validate_stock_name(self, stock_code: str, proposed_name: str = None) -> StockInfo:
        """校对股票名称"""
        stock_code = stock_code.strip()
        
        # 优先级: 配置文件注释 > 手动维护 > 提议名称 > 默认
        final_name = None
        source = "unknown"
        confidence = 0.5
        
        # 1. 检查配置文件注释
        if stock_code in self.config_stock_names:
            final_name = self.config_stock_names[stock_code]
            source = "config"
            confidence = 0.9
            
        # 2. 检查手动维护的映射
        elif stock_code in self.manual_stock_names:
            final_name = self.manual_stock_names[stock_code]
            source = "manual"
            confidence = 0.8
            
        # 3. 使用提议的名称
        elif proposed_name and proposed_name != f"股票{stock_code}":
            final_name = proposed_name
            source = "proposed"
            confidence = 0.6
            
        # 4. 默认名称
        else:
            final_name = f"股票{stock_code}"
            source = "default"
            confidence = 0.3
        
        stock_info = StockInfo(
            code=stock_code,
            name=final_name,
            source=source,
            confidence=confidence
        )
        
        self.validated_names[stock_code] = stock_info
        return stock_info
    
    def batch_validate(self, stock_codes: List[str]) -> Dict[str, StockInfo]:
        """批量校对股票名称"""
        results = {}
        for code in stock_codes:
            results[code] = self.validate_stock_name(code)
        return results
    
    def get_validation_report(self) -> Dict[str, any]:
        """获取校对报告"""
        if not self.validated_names:
            return {"status": "no_validation_performed"}
        
        source_stats = {}
        confidence_stats = {"high": 0, "medium": 0, "low": 0}
        
        for stock_info in self.validated_names.values():
            # 统计来源
            source_stats[stock_info.source] = source_stats.get(stock_info.source, 0) + 1
            
            # 统计置信度
            if stock_info.confidence >= 0.8:
                confidence_stats["high"] += 1
            elif stock_info.confidence >= 0.6:
                confidence_stats["medium"] += 1
            else:
                confidence_stats["low"] += 1
        
        return {
            "total_validated": len(self.validated_names),
            "source_breakdown": source_stats,
            "confidence_breakdown": confidence_stats,
            "low_confidence_stocks": [
                {"code": info.code, "name": info.name, "confidence": info.confidence}
                for info in self.validated_names.values()
                if info.confidence < 0.6
            ]
        }
    
    def suggest_corrections(self) -> List[Dict[str, str]]:
        """建议需要修正的股票名称"""
        corrections = []
        
        for stock_info in self.validated_names.values():
            if stock_info.confidence < 0.6:
                corrections.append({
                    "code": stock_info.code,
                    "current_name": stock_info.name,
                    "source": stock_info.source,
                    "suggestion": "需要手动验证或添加到配置文件"
                })
        
        return corrections
    
    def initialize(self):
        """初始化校对器"""
        self.parse_config_with_comments()
        self.load_manual_stock_names()
        self.logger.info("股票名称校对器初始化完成")

# 全局实例
_validator_instance = None

def get_stock_name_validator() -> StockNameValidator:
    """获取股票名称校对器单例"""
    global _validator_instance
    if _validator_instance is None:
        _validator_instance = StockNameValidator()
        _validator_instance.initialize()
    return _validator_instance

def validate_stock_name(stock_code: str, proposed_name: str = None) -> StockInfo:
    """便捷函数：校对单个股票名称"""
    validator = get_stock_name_validator()
    return validator.validate_stock_name(stock_code, proposed_name) 